/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sle_hilog.h"
#include "cmd_input.h"
#include "sle_error_code.h"
#include "sle_lite_tool_ssap_client.h"
#include "sle_dev_ssap_connect.h"
#include "sle_type_trans_utils.h"
#include "sle_ssap_config.h"
#include "sle_iperf_common.h"

static void TSleIperfToolCmdHelp(void);

static void TSleUpdateConnParamValue(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${interval} ${latency} ${supervisionTimeout}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 1 22 0 500  \r\n", __func__);
    SleConnectionParamUpdateEvt mParam = {0};
    mParam.interval = SleGetInputNumber("interval");
    mParam.latency = SleGetInputNumber("latency");
    mParam.supervisionTimeout = SleGetInputNumber("supervisionTimeout");
    UpdateSleConnParamValue(&mParam);
}

static void TSleSsapConnect(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${remoteSleDevAddr}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 2 01:02:03:04:05:06  \r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:aa:bb:f1:6b)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);
    printf("%s: will connect to remote device addr(%02x:%02x:%02x:%02x:%02x:%02x)\r\n", __func__,
        remoteAddr.addr[0],remoteAddr.addr[1],remoteAddr.addr[2],remoteAddr.addr[3],remoteAddr.addr[4],remoteAddr.addr[5]);
    SleErrorCode ret = SleSsapConnectRemoteSsapServer(&remoteAddr);
    if(ret != SLE_NO_ERROR) {
        printf("%s: SleSsapConnect remote device failed, ret:%hhu\r\n", __func__, ret);
        return;
    }
}

static void SleSsapDisconnect(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${remoteSleDevAddr}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 3 01:02:03:04:05:06  \r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:22:33:44:55)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);
    SleErrorCode ret = SleDisconnect(&remoteAddr);
    if(ret != SLE_NO_ERROR) {
        printf("[SleConnectTestTool] SleDisconnect failed, ret:%hhu\r\n", ret);
        return;
    }
}

static void TSleThroughputClientToServerTest(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${sleAddr} ${timeConsume_sec} ${packageSum}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 4 01:02:03:04:05:06 0 10000  \r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:22:33:44:55)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);

    int32_t durationSeconds = SleGetInputNumber("Please input Test duration seconds, 0 is use default settings.");
    int32_t sendPackageSum = SleGetInputNumber("Please input send package nums, 0 is use default settings: ");
    SLE_LOGI("%s: Get targetAddr[%02x:%02x:%02x:%02x:%02x:%02x], testSeconds[%d], sendPackageSum[%d]", __func__,
        remoteAddr.addr[0],remoteAddr.addr[1],remoteAddr.addr[2],remoteAddr.addr[3],remoteAddr.addr[4],remoteAddr.addr[5],
        durationSeconds, sendPackageSum);
    SleThroughputSsapsTest(&remoteAddr, durationSeconds, sendPackageSum);
}


static void TSleThroughputServerToClientTest(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${sleAddr} ${timeConsume_sec} ${packageSum}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 5 01:02:03:04:05:06 0 10000  \r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:22:33:44:55)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);

    int32_t durationSeconds = SleGetInputNumber("Please input Test duration seconds, 0 is use default settings.");
    int32_t sendPackageSum = SleGetInputNumber("Please input send package nums, 0 is use default settings: ");
    SleThroughputSsapsTest(&remoteAddr, durationSeconds, sendPackageSum);
}

static void TSleLatencyTest(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${sleAddr} ${interval_msec} ${packageSum} ${timeConsume_sec}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 6 01:02:03:04:05:06 20 50 0  \r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:22:33:44:55)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);
    int32_t sendInterval = SleGetInputNumber("Please input send each package interval(millisecond): ");
    int32_t sendPackageSum = SleGetInputNumber("Please input send package nums, 0 is use default settings: ");
    int32_t durationSeconds = SleGetInputNumber("Please input Test duration seconds, 0 is use default settings.");
    SleLatencySsapcTest(&remoteAddr, durationSeconds, sendPackageSum, sendInterval);
}

static void TSleStabilityTest(void)
{
    SLE_LOGI("[cmd format]: AT+KHCOMMONTOOL=--SleIperfTool ${cmdIndex} ${sleAddr} ${timeConsume_sec} ${packageSum} ${interval_msec}  \r\n", __func__);
    SLE_LOGI("[ cmd  exp ]: AT+KHCOMMONTOOL=--SleIperfTool 7 01:02:03:04:05:06 3600 3600 1000\r\n", __func__);
    SleDeviceAddress remoteAddr = {
        .addrType = SLE_PUBLIC_ADDRESS_TYPE,
    };
    char addr[18];
    SleGetInputString("Please input remote device public addr(00:11:22:33:44:55)", addr, sizeof(addr));
    if(strlen(addr) != 17) {
        printf("%s: Get remote dev addr param failed, invalid addr\r\n", __func__);
        return;
    }
    Str2Mac(remoteAddr.addr, addr);
    int32_t durationSeconds = SleGetInputNumber("Please input Test duration seconds, 0 is use default settings.");
    int32_t sendPackageSum = SleGetInputNumber("Please input send package nums, 0 is use default settings: ");
    int32_t sendInterval = SleGetInputNumber("Please input send each package interval(millisecond): ");
    
    SleStabilityTest(&remoteAddr, durationSeconds, sendPackageSum, sendInterval);
}

static CmdNode g_hostCmdList[] = {
    {"SleIperfToolCmdHelp", TSleIperfToolCmdHelp},
    {"SleUpdateConnParamValue", TSleUpdateConnParamValue},
    {"SleSsapConnect", TSleSsapConnect},
    {"SleSsapDisconnect", SleSsapDisconnect},
    {"SleThroughputClientToServerTest", TSleThroughputClientToServerTest},
    {"SleThroughputServerToClientTest", TSleThroughputServerToClientTest},
    {"SleLatencyTest", TSleLatencyTest},    //SsapClient to SsapServer
    {"SleStabilityTest", TSleStabilityTest},
};

static void TSleIperfToolCmdHelp(void)
{
    printf("****SleIperfTool At Command List*****\r\n");
    int g_hostCmdNum = sizeof(g_hostCmdList)/sizeof(g_hostCmdList[0]);
    for (uint16_t i = 0; i < g_hostCmdNum; i++) {
        printf("*     %02d - %-20s     *\r\n", i, g_hostCmdList[i].desc);
    }
    printf("*************************************\r\n");
}

void SleIperfToolATCmdHandler(int argc, char **argv)
{
    //试配uart接口的调用方式
    SleResetEnv();
    //从函数名字之后开始处理参数列表
    SleSetBufEnv(argc, argv, 1);
    int g_hostCmdNum = sizeof(g_hostCmdList)/sizeof(g_hostCmdList[0]);
    int index = SleGetInputNumber("Please input cmd index:\r\n");
    if (index < g_hostCmdNum) {
        printf("cmd: %d\r\n", index);
        printf("Execute: %s\r\n", g_hostCmdList[index].desc);
        g_hostCmdList[index].func();
    }
    if (index != 0) {
        g_hostCmdList[0].func();
    }
}